"""
测试用例执行模块
负责执行HTTP请求并支持参数化
"""
import requests
import json
import re
import time
from typing import Dict, Any, Tuple


class CaseExecutor:
    """测试用例执行器"""
    
    def __init__(self, parameters: Dict[str, str] = None):
        """
        初始化执行器
        :param parameters: 全局参数字典 {param_name: param_value}
        """
        self.parameters = parameters or {}
    
    def replace_parameters(self, text: str) -> str:
        """
        替换文本中的参数占位符 ${param_name}
        :param text: 原始文本
        :return: 替换后的文本
        """
        if not isinstance(text, str):
            return text
        
        # 查找所有 ${...} 格式的占位符
        pattern = r'\$\{([^}]+)\}'
        
        def replacer(match):
            param_name = match.group(1)
            if param_name in self.parameters:
                return str(self.parameters[param_name])
            else:
                # 如果参数不存在，保持原样
                return match.group(0)
        
        return re.sub(pattern, replacer, text)
    
    def replace_in_dict(self, data: Any) -> Any:
        """
        递归替换字典/列表中的参数
        :param data: 原始数据
        :return: 替换后的数据
        """
        if isinstance(data, dict):
            return {k: self.replace_in_dict(v) for k, v in data.items()}
        elif isinstance(data, list):
            return [self.replace_in_dict(item) for item in data]
        elif isinstance(data, str):
            return self.replace_parameters(data)
        else:
            return data
    
    def execute(self, case_data: Dict) -> Tuple[bool, Dict]:
        """
        执行测试用例
        :param case_data: 包含 domain, url_path, method, headers, body 的字典
        :return: (success, result_dict)
        """
        start_time = time.time()
        result = {
            'success': False,
            'status_code': None,
            'response_body': None,
            'response_headers': None,
            'execution_time': 0,
            'error_message': None
        }
        
        try:
            # 替换URL中的参数
            domain = self.replace_parameters(case_data['domain'])
            url_path = self.replace_parameters(case_data['url_path'])
            full_url = domain + url_path
            
            # 替换headers中的参数
            headers = self.replace_in_dict(case_data.get('headers', {}))
            
            # 替换body中的参数
            body = self.replace_in_dict(case_data.get('body', {}))
            
            # 执行HTTP请求
            method = case_data.get('method', 'GET').upper()
            
            print(f"执行请求: {method} {full_url}")
            print(f"Headers: {json.dumps(headers, indent=2, ensure_ascii=False)}")
            print(f"Body: {json.dumps(body, indent=2, ensure_ascii=False)}")
            
            if method == 'GET':
                response = requests.get(full_url, headers=headers, timeout=30)
            elif method == 'POST':
                response = requests.post(full_url, headers=headers, json=body, timeout=30)
            elif method == 'PUT':
                response = requests.put(full_url, headers=headers, json=body, timeout=30)
            elif method == 'DELETE':
                response = requests.delete(full_url, headers=headers, timeout=30)
            elif method == 'PATCH':
                response = requests.patch(full_url, headers=headers, json=body, timeout=30)
            else:
                raise ValueError(f"不支持的HTTP方法: {method}")
            
            # 记录响应
            result['status_code'] = response.status_code
            result['response_headers'] = dict(response.headers)
            
            # 尝试解析JSON响应
            try:
                result['response_body'] = response.json()
            except:
                result['response_body'] = response.text
            
            # 判断是否成功（2xx状态码）
            result['success'] = 200 <= response.status_code < 300
            
        except requests.exceptions.Timeout:
            result['error_message'] = "请求超时"
        except requests.exceptions.ConnectionError:
            result['error_message'] = "连接错误"
        except Exception as e:
            result['error_message'] = str(e)
        
        # 计算执行时间
        result['execution_time'] = time.time() - start_time
        
        return result['success'], result
    
    def extract_value_from_response(self, response_body: Any, json_path: str) -> Any:
        """
        从响应体中提取值（支持简单的JSON路径）
        例如: data.user.id 或 data[0].name
        :param response_body: 响应体（可以是dict或list）
        :param json_path: JSON路径
        :return: 提取的值
        """
        if not json_path:
            return response_body
        
        current = response_body
        parts = json_path.split('.')
        
        try:
            for part in parts:
                # 处理数组索引 data[0]
                if '[' in part and ']' in part:
                    key = part[:part.index('[')]
                    index = int(part[part.index('[')+1:part.index(']')])
                    if key:
                        current = current[key][index]
                    else:
                        current = current[index]
                else:
                    current = current[part]
            return current
        except (KeyError, IndexError, TypeError) as e:
            print(f"提取值失败: {json_path}, 错误: {e}")
            return None


def test_executor():
    """测试执行器"""
    # 模拟参数
    params = {
        'user_id': '12345',
        'token': 'test_token_abc'
    }
    
    executor = CaseExecutor(params)
    
    # 测试用例
    case = {
        'domain': 'https://jsonplaceholder.typicode.com',
        'url_path': '/posts/${user_id}',
        'method': 'GET',
        'headers': {
            'Authorization': 'Bearer ${token}',
            'Content-Type': 'application/json'
        },
        'body': {}
    }
    
    success, result = executor.execute(case)
    print(f"执行结果: {success}")
    print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    test_executor()

